import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
import { Subject } from "rxjs/Subject";
import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";
import { CmHttp } from "CmHttp";
import { VtradeTerminalService } from "./../vtradeterminal.service";
import { HsClientService } from "./../../hs-client.service";
import { SheetDataType } from "./../vtradeterminal.model";
import { SummaryNameService, SearchStockClass, LOCALSEARCH, BASEURL, STOCKURL } from "shared";

interface VtradeType {
  symbol: string;  // 股票代码
  name: string;  // 股票名称
  amount: number;  // 买入数量
  price: number;  // 买入价格
}

// 交易状态，START: 市场启动, PRETR: 盘前, OCALL: 开始集合竞价, TRADE: 交易（连续撮合）, HALT: 暂停交易, SUSP: 停盘, BREAK: 休市, POSTR: 盘后, ENDTR: 交易结束
// interface TRADETYPE {
//   START: "START";
//   PRETR: "PRETR";
//   OCALL: "OCALL";
//   TRADE: "TRADE";
//   HALT: "HALT";
//   SUSP: "SUSP";
//   BREAK: "BREAK";
//   POSTR: "POSTR";
//   ENDTR: "ENDTR";
//   STOPT: "STOPT";
// }

const TSTATUS = {
  START: "START",
  PRETR: "PRETR",
  OCALL: "OCALL",
  TRADE: "TRADE",
  HALT: "HALT",
  SUSP: "SUSP",
  BREAK: "BREAK",
  POSTR: "POSTR",
  ENDTR: "ENDTR",
  STOPT: "STOPT",
};

@Component({
  selector: 'vtrade-buyin',
  templateUrl: 'vtradebuyin.component.html',
  styleUrls: ['vtradebuyin.component.less']
})
export class VtradeBuyinComponent implements OnInit, OnDestroy {
  @Input() stockSource;  // detail
  @Input() summarySource;  // available amount
  @Input() tradeTypeSource;  // buyin, saleout
  @Input() priceUpdateSource;  // bidask price
  @Input() emptySource;  // for MRI and XBHS
  @Output() onChangeSymbol = new EventEmitter();
  @Output() onConfirm = new EventEmitter();
  @Output() onError = new EventEmitter();
  @ViewChild("inputSymbolRef") symbolRef: ElementRef;
  @ViewChild("inputPriceRef") priceRef: ElementRef;
  @ViewChild("inputAmountRef") amountRef: ElementRef;
  holdingList = [{
    key: "full",
    label: "全仓",
  }, {
    key: "half",
    label: "半仓",
  }, {
    key: "one-third",
    label: "1/3仓",
  }, {
    key: "two-third",
    label: "2/3仓",
  }, {
    key: "quarter",
    label: "1/4仓",
  }, {
    key: "one-tenth",
    label: "1/10仓",
  }];

  strategies = [{
    key: 'current',
    label: '限价委托'
  }, {
    key: 'bidask',
    label: '市价委托'
  }];
  vtradeObj: VtradeType;  // 存储到service, 用于同时买卖
  inputSymbol: string;  // 股票代码
  inputSymbolBackup: string;  // 股票代码
  inputName: string;  // 股票名称
  inputAmount: number = 0;  // 买入数量
  inputPrice: number;  // 买卖价格
  stockMarket: string;  // 所属市场
  up_price: string;  // 涨停价
  down_price: string;  // 跌停价

  account: string;  // 账户id
  enable_balance: string;  // 可用资金
  inputAvailable: number;  // 可买股数, 可用资金/买入价格 取整百
  ask_one_price: string;  // 卖一价格 for 买入市价委托
  bid_one_price: string;  // 买一价格 for 卖出市价委托
  vtrade = {};
  tradeType: string = '';
  BUYIN = {
    formTitle: '买入股票',
    priceTitle: '价格',
    availableTitle: '可买',
    amountTitle: '数量',
    actionTitle: '买入'
  };
  SALEOUT = {
    formTitle: '卖出股票',
    priceTitle: '价格',
    availableTitle: '可卖',
    amountTitle: '数量',
    actionTitle: '卖出'
  };
  // 用于生成委托单
  sheetData: SheetDataType;
  // 本地缓存
  localDB: Array<SearchStockClass> = [];
  handleResultSub = new Subject();
  tradeStatus: string;
  isMRIorXBHS = false;

  constructor(private http: CmHttp,
    private vts: VtradeTerminalService,
    private hsClient: HsClientService,
    private sns: SummaryNameService) {
    sns.summaryNameSub.subscribe((res: Array<SearchStockClass>) => {
      this.localDB = res;
      // console.debug('%c LocalDB: ', 'color:#F09', this.localDB);
    });
  }

  tradeTypeSubscription: Subscription;
  stockSubscription: Subscription;
  summarySubscription: Subscription;
  searchSubscription: Subscription;
  searchResultSubscription: Subscription;
  priceUpdateSubscription: Subscription;
  keydownSubscription: Subscription;

  ngOnInit() {
    // 设定股票交易的类型
    this.tradeTypeSubscription = this.tradeTypeSource.subscribe(type => {
      this.tradeType = type;
      if (type === 'buyin') {
        this.vtrade = this.BUYIN;
      } else if (type === 'saleout') {
        this.vtrade = this.SALEOUT;
      }
      // this.sheetData.type = type;
    });

    this.stockSubscription = this.stockSource.subscribe(res => {
      console.debug('vtrade buyin data source:', res);
      console.log('isShowSearchList: ', this.isShowSearchList);
    });
    // 处理股票的数据流
    this.summarySubscription = Observable.combineLatest(
      this.stockSource,
      this.summarySource,
      (stock, account) => Object.assign({}, { stock }, { account })
    ).subscribe(data => {
      console.debug('%c BUYIN combineLatest data:', 'color:#F09', data);
      if (this.isMRIorXBHS) return;

      this.tradeStatus = data.stock["status"];

      if (data.stock) {
        this.setStockValue(data.stock);
      }
      this.enable_balance = data.account['enable_balance'];
      // this.account = "A0" + data.account['account'];
      // this.account = data.account['account'];
      this.account = "";
      if (this.tradeType === 'saleout') {
        if (this.tradeStatus === TSTATUS.SUSP || this.tradeStatus === TSTATUS.STOPT) return;
        // 可卖数量 = 昨日该股结算持仓数量，可以出现零股
        let param = {
          exchange_type: this.stockMarket.indexOf('XSHG') > -1 ? "1" : "2",  // 1 for 上证, 2 for 深证
          stock_account: this.account,
          stock_code: this.inputSymbolBackup,
          entrust_prop: "0",  // 0 for 买卖, 3 for 申购
        };
        console.log('query amount sale request param:', param);
        this.hsClient.queryAmountSale(param).subscribe(res => {
          console.log('query amount sale res:', res[0]);
          this.inputAvailable = parseInt(res[0].enable_amount);
        });
      } else {
        this.calcAvailableAmount();
      }
    });

    // 置空数据
    this.emptySource ? this.emptySource.subscribe((val: boolean) => {
      this.isMRIorXBHS = val;
      if (!val) return;
      this.inputSymbol = "";  // 股票代码
      this.inputSymbolBackup = "";  // 股票代码
      this.inputName = "";  // 股票名称
      this.inputAmount = 0;  // 买入数量
      this.inputPrice = 0;  // 买卖价格
      this.inputAvailable = 0;
    }) : null;

    // 开始搜索股票
    this.searchSubscription = this.searchActionSub
      // .debounceTime(100)
      .distinctUntilChanged()
      .map(input => {
        // let a = input.match(/[a-zA-Z0-9\.]{1,}/g);  // 字母数字和. for online search
        let a = input.match(/[\u4e00-\u9fa5a-zA-Z0-9\.]{1,}/g);  // 中文,字母,数字和.
        return a ? a[0] : a;
      })
      .subscribe(value => {
        if (!value) {
          return false;
        }

        let keyword = value.toUpperCase();
        // console.log("teriminal search request data: ", keyword);
        if (LOCALSEARCH === "enable") {
          let results = [];
          let count = 0, limitLine = 20;

          // local search
          this.localDB.forEach((v, i) => {
            if (count > limitLine - 1) {
              return;
            }
            try {
              if (v.symbol.indexOf(keyword) >= 0 ||
                v.abbr.indexOf(keyword) >= 0 ||
                v.name.indexOf(keyword) >= 0
              ) {
                results.push(v);
                count++;
              }
            } catch (e) {
              console.error('input value indexOf summary:', e);
            }
          });
          // console.log("search results: ", results);
          this.handleResultSub.next(results);
        } else {
          // online search
          this.http.get(`${BASEURL}/stock/search?key=${keyword}`, {})
            .subscribe(res => {
              console.log("online search results: ", res);
              this.handleResultSub.next(res);
            });
        }
      });

    // handle search result
    this.handleResultSub.subscribe((res: Array<SearchStockClass>) => {
      // 根据路由位置返回不同的结果, 交易页面的搜索不显示股指和板块的结果
      this.searchStocks = res.filter(stock => stock.market.indexOf('MRI') === -1 && stock.market.indexOf('XBHS') === -1);

      // 启用无结果提示
      this.enableEmptyResult = true;
      if (this.searchStocks.length) {
        this.selectedIndex = 1;
        this.selectedStock = this.searchStocks[0];
      } else {
        this.selectedIndex = 0;
        this.selectedStock = null;
      }
    });

    // 切换为选中的搜索结果股票的数据流
    this.searchResultSubscription = this.searchStockSub.filter(quote => quote["symbol"]).switchMap(quote =>
      Observable.zip(
        http.get(`${STOCKURL}/api/v2/sc/stocks/f10/${quote["symbol"]}/headlines`, {}, {cacheAge: http.CACHE_AGE.Instant}),
        this.http.get(`${STOCKURL}/api/v2/sc/charts/${quote["symbol"]}/summary`),
        (fData, detail) => Object.assign({}, detail.data, fData.data)
      )
    ).subscribe(res => {
      this.stockSource.next(res);
      // 变更股票之后，往外更新k线图
      this.onChangeSymbol.next(res);
    });

    // 通过买卖五档或涨跌停价格的点击来动态更新交易终端的价格
    this.priceUpdateSubscription = this.priceUpdateSource.subscribe(res => {
      // console.log('priceUpdateSource: ', res);
      if (res.type === this.tradeType) {
        this.inputPrice = parseFloat(res.price);
      }
    });
  }

  ngOnDestroy() {
    this.tradeTypeSubscription ? this.tradeTypeSubscription.unsubscribe() : null;
    this.stockSubscription ? this.stockSubscription.unsubscribe() : null;
    this.summarySubscription ? this.summarySubscription.unsubscribe() : null;
    this.searchSubscription ? this.searchSubscription.unsubscribe() : null;
    this.searchResultSubscription ? this.searchResultSubscription.unsubscribe() : null;
    this.priceUpdateSubscription ? this.priceUpdateSubscription.unsubscribe() : null;
    this.keydownSubscription ? this.keydownSubscription.unsubscribe() : null;
  }

  // 交易数据有效性检测
  private validCheck(type = "buy") {
    let a = true;
    if (!this.inputSymbolBackup) {
      // console.warn('symbol empty.');
      this.onError.next('请输入股票名称');
      a = false;
      return false;
    }

    console.debug("%c current trade status: ", 'color: #DF0', this.tradeStatus);
    // 停牌检测
    if (this.tradeStatus !== TSTATUS.TRADE && this.tradeStatus !== TSTATUS.OCALL) {
      let msg = "";
      switch (this.tradeStatus) {
        case TSTATUS.SUSP:
        case TSTATUS.STOPT:
          msg = "该股票已停牌";
          break;
        case TSTATUS.START:
        case TSTATUS.PRETR:
          // case TSTATUS.OCALL:  // 委托和撤单, 委托和不能撤单
          msg = "尚未到交易时段";
          break;
        case TSTATUS.HALT:
          msg = "该股票暂停交易";
          break;
        case TSTATUS.BREAK:
          msg = "已休市";
          break;
        case TSTATUS.POSTR:
        case TSTATUS.ENDTR:
          msg = "交易结束";
          break;
      }
      this.onError.next(msg);
      a = false;
      return false;
    }

    if (!this.inputPrice) {
      // console.warn('price empty.');
      this.onError.next('请输入股票价格');
      a = false;
      return false;
    }

    // price valid check
    if (this.checkPrice()) {
      a = false;
      return false;
    }

    if (!this.inputAmount) {
      // console.warn('amount empty.');
      this.onError.next('请输入股票数量');
      a = false;
      return false;
    }

    if (this.inputAmount > this.inputAvailable) {
      if (type === "sell") {
        this.onError.next('可卖数量不足');
      } else {
        this.onError.next('可买数量不足');
      }
      a = false;
      return false;
    }
    return a;
  }

  private checkPrice() {
    // 获取原始输入框的价格
    let val = this.priceRef.nativeElement.value;

    if (val > Number.parseFloat(this.up_price)) {
      this.onError.next("股票价格超过涨停价格");
      return true;
    }
    if (val < Number.parseFloat(this.down_price)) {
      this.onError.next("股票价格超过跌停价格");
      return true;
    }
    let pstr = val.toString().match(/(\d+\.?\d{3})/g);
    console.debug("valid check pstr: ", pstr);
    if (pstr && pstr.length) {
      this.onError.next("股票价格小数位数过多");
      return true;
    }
    return false;
  }

  // 设定股票的显示数据
  private setStockValue(stock) {
    this.inputSymbol = stock.symbol;
    this.inputSymbolBackup = stock.symbol;
    this.inputName = stock.name;
    this.inputPrice = parseFloat(stock.current);
    this.stockMarket = stock.market;

    this.up_price = stock.up_price;
    this.down_price = stock.down_price;
    // 卖一 for buyin
    let asks = stock.ask.split(',');
    this.ask_one_price = asks[0];
    // 买一 for saleout
    let bids = stock.bid.split(',');
    this.bid_one_price = bids[0];
  }

  // 大约可买数量获取
  private calcAvailableAmount() {
    // 如果是卖出股票则不更新
    if (this.tradeType === 'saleout') return;
    if (this.inputPrice) {
      this.inputAvailable = Math.floor(parseFloat(this.enable_balance) / this.inputPrice / 100) * 100;
    } else {
      this.inputAvailable = 0;
    }
  }

  // 是否显示搜索列表
  isShowSearchList = false;
  isPriceFocus = false;
  isAmountFocus = false;
  searchActionSub: Subject<any> = new Subject<any>();
  searchStockSub: Subject<any> = new Subject<any>();
  searchStocks = [];  // 搜索结果
  selectedStock: SearchStockClass;  // 选中的搜索结果
  selectedIndex: number = 1;  // 选中的搜索结果自然顺序
  enableEmptyResult = false;

  // 选取搜索结果的股票
  selectSymbol(stock: SearchStockClass) {
    console.log('terminal select symbol: ', stock);
    this.enableEmptyResult = false;
    this.isShowSearchList = false;
    // 快速显示symbol, name
    this.inputSymbol = stock.symbol;
    this.inputSymbolBackup = stock.symbol;
    this.inputName = stock.name;
    // 获取详细数据
    this.searchStockSub.next(stock);
  }

  // 焦点放入搜索框
  focusSearch(e) {
    this.inputSymbol = e.target.value.replace(/\.[a-zA-Z]*/g, '');
  }

  // 动态更新 for ngModelChange
  onDataChange(val: string) {
    console.debug("on vtrade Data change value: ", val);
    if (val) {
      this.isShowSearchList = true;
      this.searchActionSub.next(val);
    } else {
      this.isShowSearchList = false;
    }
  }

  // 在证券代码栏键入处理, 快速进入买入/卖出价格
  onSymbolKeyboardHandler(e: KeyboardEvent) {
    // console.debug("symbol key handler: ", e, e.keyCode, e.key, e.code);
    // 搜索结果框开启时，禁用输入框的上下左右移动操作
    if (this.isShowSearchList && this.searchStocks.length) {
      // 高亮上一条搜索结果记录, 键盘上, -, page up
      if (e.key === "ArrowUp" || e.key === "ArrowLeft" || e.key === "PageUp" || e.key === "-") {
        if (this.selectedIndex) {
          if (this.selectedIndex > 1) {
            this.selectedIndex--;
            this.selectedStock = this.searchStocks[this.selectedIndex - 1];
          }
        }
        e.preventDefault();
      }
      // 高亮下一条搜索结果记录, 键盘下, +, page down
      if (e.key === "ArrowDown" || e.key === "ArrowRight" || e.key === "PageDown" || e.key === "+") {
        if (this.selectedIndex < this.searchStocks.length) {
          this.selectedIndex++;
          this.selectedStock = this.searchStocks[this.selectedIndex - 1];
        }
        e.preventDefault();
      }

      // enter 选取当前的搜索结果
      if (this.searchStocks.length && e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
        if (!this.selectedStock) {
          this.selectedStock = this.searchStocks[0];
        }
        this.selectSymbol(this.selectedStock);
      }
    }

    // 跳到价格栏
    if (!this.isShowSearchList) {
      if ((e.key === "Enter" || e.key === "Tab") && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
        this.priceRef.nativeElement.focus();
        e.preventDefault();
      }
    }
  }

  // 更改交易策略
  changeStrategy(st: string) {
    // console.log('strategy: ', st);
    switch (st) {
      case '市价委托':
        if (this.tradeType === 'buyin') {
          this.inputPrice = parseFloat(this.ask_one_price);  // 卖一价格 for 买入
        } else if (this.tradeType === 'saleout') {
          this.inputPrice = parseFloat(this.bid_one_price);  // 买一价格 for 卖出
        }
        break;
      case '现价委托':
        break;
    }
  }

  // updateKeyupPrice
  updateKeyupPrice(e: KeyboardEvent) {
    // console.log("value: ", e.key, e.keyCode, this.inputPrice);
    // allowed key
    if ((e.keyCode >= 48 && e.keyCode <= 57 && !e.shiftKey) ||  // 0 - 9 and unshifted
      (e.keyCode >= 96 && e.keyCode <= 105) ||  // 0 - 9 for number pad
      e.key === "."  // .
    ) {
      let val = this.inputPrice;
      if (val >= Number.parseFloat(this.up_price)) {
        this.inputPrice = parseFloat(this.up_price);
      } else if (val <= Number.parseFloat(this.down_price)) {
        this.inputPrice = parseFloat(this.down_price);
      } else {
        this.inputPrice = Math.floor(val * 1000) / 1000;
      }
      this.calcAvailableAmount();
    }
  }

  // 点击+-更新price
  changePrice(type: string) {
    // console.log('change price: ', type);
    switch (type) {
      case "+":
        if (this.inputPrice >= Number.parseFloat(this.up_price)) {
          this.inputPrice = parseFloat(this.up_price);
        } else {
          this.inputPrice = this.inputPrice + 0.01;
        }

        this.calcAvailableAmount();
        break;
      case "-":
        if (this.inputPrice <= Number.parseFloat(this.down_price)) {
          this.inputPrice = parseFloat(this.down_price);
        } else {
          this.inputPrice = this.inputPrice - 0.01;
        }

        this.calcAvailableAmount();
        break;
    }
  }

  // 在买入/卖出价格栏键入, 快速进入买入/卖出数量
  onPriceKeyboardHandler(e: KeyboardEvent) {
    // e.stopPropagation();
    // 通过+-快速调整
    if (e.key === "-" || e.key === "_") {
      this.changePrice("-");
      e.preventDefault();
    }
    if (e.key === "=" || e.key === "+") {
      this.changePrice("+");
      e.preventDefault();
    }
    // 跳到数量栏
    if ((e.key === "Enter" || e.key === "Tab") && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
      this.amountRef.nativeElement.focus();
      e.preventDefault();
    }
  }

  onBlurUpdateAmount(val: number) {
    this.inputAmount = Math.floor(val / 100) * 100;  // 100n for amount
    this.isAmountFocus = false;
    // console.log('blur amount: ', val, this.inputAmount);
  }

  // 点击+-或仓位时更新amount
  changeAmount(type: string) {
    // console.log('changeAmount : ', this.inputAmount, this.inputAvailable);
    if (!this.inputAmount) {
      this.inputAmount = 0;
    }
    let tempAmount = 0;
    switch (type) {
      case "+":
        if (this.inputAmount >= this.inputAvailable - 100) {
          this.inputAmount = this.inputAvailable;
        } else {
          this.inputAmount = this.inputAmount + 100;
        }
        break;
      case "-":
        if (this.inputAmount <= 100) {
          this.inputAmount = 0;
        } else {
          this.inputAmount = this.inputAmount - 100;
        }
        break;
      case "full":
        this.inputAmount = Math.floor(this.inputAvailable / 100) * 100;  // 100n for amount
        break;
      case "two-third":
        tempAmount = Math.floor(this.inputAvailable * 2 / 300) * 100;  // 100n for amount
        this.inputAmount = (!tempAmount && this.inputAvailable > 100) ? 100 : tempAmount;
        break;
      case "half":
        tempAmount = Math.floor(this.inputAvailable / 200) * 100;  // 100n for amount
        this.inputAmount = (!tempAmount && this.inputAvailable > 100) ? 100 : tempAmount;
        break;
      case "one-third":
        tempAmount = Math.floor(this.inputAvailable / 300) * 100;  // 100n for amount
        this.inputAmount = (!tempAmount && this.inputAvailable > 100) ? 100 : tempAmount;
        break;
      case "quarter":
        tempAmount = Math.floor(this.inputAvailable / 400) * 100;  // 100n for amount
        this.inputAmount = (!tempAmount && this.inputAvailable > 100) ? 100 : tempAmount;
        break;
      case "one-tenth":
        tempAmount = Math.floor(this.inputAvailable / 1000) * 100;  // 100n for amount
        this.inputAmount = (!tempAmount && this.inputAvailable > 100) ? 100 : tempAmount;
        break;
    }
  }

  // 在买入/卖出数量上键入, 快速进入交易操作
  onAmountKeyboardHandler(e: KeyboardEvent) {
    // e.stopPropagation();
    // 通过+-快速调整
    if (e.key === "-" || e.key === "_") {
      this.changeAmount("-");
      e.preventDefault();
    }
    if (e.key === "=" || e.key === "+") {
      this.changeAmount("+");
      e.preventDefault();
    }
    // 跳到交易按键
    if ((e.key === "Enter" || e.key === "Tab") && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
      if (this.tradeType === "buyin") {
        this.buyin();
      } else {
        this.saleout();
      }
      e.preventDefault();
    }
  };

  // 数据类型
  sendOutSheetData: SheetDataType;
  // 点击终端买入
  buyin() {
    console.log('buyin click:', this.inputPrice);
    if (!this.validCheck()) return;
    this.sendOutSheetData = {
      type: 'buyin',
      buyin: {
        account: this.account,
        symbol: this.inputSymbolBackup,
        name: this.inputName,
        price: this.priceRef.nativeElement.value,
        amount: this.inputAmount,
        market: this.stockMarket
      }
    };
    console.log('buyin click:', this.sendOutSheetData);
    this.onConfirm.next(this.sendOutSheetData);
  }
  // 点击终端卖出
  saleout() {
    if (!this.validCheck("sell")) return;
    this.sendOutSheetData = {
      type: 'saleout',
      saleout: {
        account: this.account,
        symbol: this.inputSymbolBackup,
        name: this.inputName,
        price: this.priceRef.nativeElement.value,
        amount: this.inputAmount,
        market: this.stockMarket
      }
    };
    console.log('saleout click:', this.sendOutSheetData);
    this.onConfirm.next(this.sendOutSheetData);
  }
}